#ifndef __DALELIB_MESH_H__
#define __DALELIB_MESH_H__

#include <assert.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;

#include "v2.h"
#include "v3.h"
#include "m4x4.h"

namespace dalelib
{

class Mesh
{
public:

	struct Vertex
	{
		v3 _pos, _nrm; v2 _uv;
		Vertex(v3 _Pos=v3(0,0,0),v3 _Nrm=v3(0,0,0),v2 _UV=v2(0,0)) : _pos(_Pos), _nrm(_Nrm), _uv(_UV) { }
	};

	struct Triangle 
	{
		int v[3]; v3 _nrm;
		Triangle(int _V0=0,int _V1=0,int _V2=0) { v[0]=_V0; v[1]=_V1; v[2]=_V2; }
	};

protected:

	typedef vector<Vertex> VertexList;
	VertexList _vertices;
	typedef vector<Triangle> TriangleList;
	TriangleList _triangles;

public:

	Mesh() { }
	~Mesh() { }	

	VertexList& getVertices() { return _vertices; }
	TriangleList& getTriangles() { return _triangles; }

	void draw()
	{
//*
		glBegin(GL_TRIANGLES);
			for(unsigned int i=0; i<_triangles.size(); ++i)
			{
				glNormal3fv(_vertices[_triangles[i].v[0]]._nrm.ptr());
				glTexCoord2fv(_vertices[_triangles[i].v[0]]._uv.ptr());
				glVertex3fv(_vertices[_triangles[i].v[0]]._pos.ptr());

				glNormal3fv(_vertices[_triangles[i].v[1]]._nrm.ptr());
				glTexCoord2fv(_vertices[_triangles[i].v[1]]._uv.ptr());
				glVertex3fv(_vertices[_triangles[i].v[1]]._pos.ptr());

				glNormal3fv(_vertices[_triangles[i].v[2]]._nrm.ptr());
				glTexCoord2fv(_vertices[_triangles[i].v[2]]._uv.ptr());
				glVertex3fv(_vertices[_triangles[i].v[2]]._pos.ptr());
			}
		glEnd();
/*/
		glDisable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		glColor3f(0,1,0);
		glBegin(GL_POINTS);
			for(unsigned int i=0; i<_vertices.size(); ++i)
			{
				glVertex3fv(_vertices[i]._pos.ptr());
			}
		glEnd();
//*/
	}

	void transform(const m4x4 _Mat)
	{
		for(unsigned int i=0; i<_vertices.size(); ++i) 
		{
			_vertices[i]._pos = _Mat.transformPoint(_vertices[i]._pos);
			_vertices[i]._nrm = _Mat.transformVector(_vertices[i]._nrm);
		}
	}

	void calcNormals()
	{
		for(unsigned int i=0; i<_vertices.size(); ++i) _vertices[i]._nrm = v3(0,0,0);
		for(unsigned int i=0; i<_triangles.size(); )
		{
			v3 v0 = _vertices[_triangles[i].v[1]]._pos-_vertices[_triangles[i].v[0]]._pos;
			v3 v1 = _vertices[_triangles[i].v[2]]._pos-_vertices[_triangles[i].v[0]]._pos;
			_triangles[i]._nrm = v1.cross(v0).unit();
			_vertices[_triangles[i].v[0]]._nrm += _triangles[i]._nrm;
			_vertices[_triangles[i].v[1]]._nrm += _triangles[i]._nrm;
			_vertices[_triangles[i].v[2]]._nrm += _triangles[i]._nrm;
			i += 3;
		}
		for(unsigned int i=0; i<_vertices.size(); ++i) _vertices[i]._nrm.normalise();
	}

};

} // namespace dalelib

#endif
